package com.itliupeng.stock.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.fasterxml.jackson.core.JsonProcessingException;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itliupeng.stock.constant.StockConstant;
import com.itliupeng.stock.mapper.*;
import com.itliupeng.stock.pojo.domain.children;
import com.itliupeng.stock.pojo.entity.SysRole;
import com.itliupeng.stock.pojo.entity.SysRolePermission;
import com.itliupeng.stock.pojo.entity.SysUser;
import com.itliupeng.stock.pojo.entity.SysUserRole;
import com.itliupeng.stock.service.UserService;
import com.itliupeng.stock.utils.IdWorker;
import com.itliupeng.stock.vo.req.LoginReqVo;
import com.itliupeng.stock.pojo.domain.queryUser;
import com.itliupeng.stock.pojo.domain.UserInfoVo;
import com.itliupeng.stock.vo.resp.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Description:
 * Author:lp
 * Date:2025-04-07
 * Time:10:01
 */
@ApiModel(description = "Description: Author:lp Date:2025-04-07 Time:10:01")
@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {

    @ApiModelProperty(hidden = true)
    @Autowired
    private PasswordEncoder passwordEncoder;
    @ApiModelProperty(hidden = true)
    @Autowired
    private SysUserMapper sysUserMapper;
    @ApiModelProperty(hidden = true)
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @ApiModelProperty(hidden = true)
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @ApiModelProperty(value = "生成雪花id", position = 5)
    @Autowired
    private IdWorker idWorker;//生成雪花id
    @ApiModelProperty(hidden = true)
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;

    @Override
    public SysUser findByUserName(String userName) {
        return sysUserMapper.findUserInfoByUserName(userName);
    }


    @Override
    public R<LoginRespVo> login(LoginReqVo loginReqVo) {

        //1.判断参数是否合法
        if (loginReqVo == null || StringUtils.isBlank(loginReqVo.getPassword()) || StringUtils.isBlank(loginReqVo.getUsername()) || StringUtils.isBlank(loginReqVo.getCode())) {
            return R.error(ResponseCode.DATA_ERROR);
        }

        //1.1判断验证码是否为空
        if (StringUtils.isBlank(loginReqVo.getCode()) || StringUtils.isBlank(loginReqVo.getSessionId())) {
            return R.error(ResponseCode.CHECK_CODE_NOT_EMPTY);
        }

        //1.2判断redis中保存到校验码是否相同（要求比较值忽略大小写）
        String redisCode = (String) redisTemplate.opsForValue().get(StockConstant.CHECK_PREFIX + loginReqVo.getSessionId());
        if (redisCode == null) {
            return R.error(ResponseCode.CHEECK_CODE_TIMEOUT);
        }
        if (!redisCode.equals(loginReqVo.getCode())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }

        //2.根据用户名去数据库查询用户信息，获取密码
        SysUser dbUser = findByUserName(loginReqVo.getUsername());
        if (dbUser == null) {
            return R.error(ResponseCode.ACCOUNT_NOT_EXISTS);
        }


        //3.调用密码匹配器匹配输入的明文密码和数据库的密文密码
        if (!passwordEncoder.matches(loginReqVo.getPassword(), dbUser.getPassword())) {
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }

        //4，响应
        LoginRespVo respVo = new LoginRespVo();

        //发现LoginRespVo与SysUser对象属性名称和类型一致,使用beanUtils.copyProperties(dbuser,respVo)自动给相同类型属性赋值
        BeanUtils.copyProperties(dbUser, respVo);
        return R.ok(respVo);
    }

    /*
     *

     * 生成图片验证码功能
     * */
    @Override
    public R<Map> getCaptchaCode() {
        /*
         * 1.生成图片验证码
         * 参数1：图片宽度
         * 参数2：图片高度
         * 参数3：图片验证码长度
         * 参数4：干扰线数量
         * */
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(250, 40, 4, 5);
        //这里还可以通过lineCaptche设置校验码的其他参数
        //获取校验码
        String code = lineCaptcha.getCode();
        //获取base64编码处理过的图片数据
        String imageDate = lineCaptcha.getImageBase64();
        //2.生成sessionid 转化成string，避免前端精度丢失
        String sessionId = String.valueOf(idWorker.nextId());

        /**
         * 注意：SpringAop做的是在运行时增强，log日志是在编译时增强，不需要实例化直接用
         *两种方法使用日志：
         * 1.就是声明参数(意思就是通过加载字节码文件，使得log在编译时就生成，可以直接使用)
         * private static final logger log = loggerFactory.getLogger(UserServiceImpl.class);
         * 2.就是使用注解的方法，自动注入上述log静态final属性的值，供我们直接使用
         * */
        log.info("当前校验码:{},会话id:{}", code, sessionId);

        //3.将sessionId作为key，校验码作为value保存在redis中,使用redis模拟session行为
        redisTemplate.opsForValue().set("CK" + sessionId, code, 5, TimeUnit.MINUTES);
        //4.组装数据
        Map<String, String> data = new HashMap<>();
        data.put("imageData", imageDate);
        data.put("sessionId", sessionId);

        return R.ok(data);
    }

    @Override
    public R<PageResult<SysUser>> getUserPage(queryUser queryUs) {
        //2.设置pageHelper分页参数,
        PageHelper.startPage(Integer.parseInt(queryUs.getPageNum()), Integer.parseInt(queryUs.getPageSize()));
        //3.查询所有数据集合
        List<SysUser> sysUsers = sysUserMapper.getUserPage(queryUs);
        //4.组装PageResult对象
        PageInfo<SysUser> sysUserPageInfo = new PageInfo<>(sysUsers);
        PageResult<SysUser> sysUserPageResult = new PageResult<>(sysUserPageInfo);
        //5.响应数据
        return R.ok(sysUserPageResult);
    }

    @Override
    public R<ResponseCode> addUser(SysUser sysUser) {

        Date date = DateTime.now().toDate();
        sysUser.setCreateTime(date);
        sysUser.setUpdateTime(date);
        sysUser.setId(idWorker.nextId());
        int insert = sysUserMapper.insert(sysUser);
        if (insert == 1) {
            return R.ok(ResponseCode.SUCCESS);
        }
        return R.error(ResponseCode.ERROR);

    }

    /**
     * 获取用户角色
     *
     * @param userId
     * @return
     */
    @Override
    public R<Map<String, List>> getUserRole(String userId) {

        List<Long> roleIds = sysUserRoleMapper.getUserRoleId(Long.parseLong(userId));
        List<SysRole> sysRoles = sysRoleMapper.getAllRole();
        Map<String, List> result = new HashMap<>();

        List<String> stringList = roleIds.stream()
                .map(String::valueOf)
                .collect(Collectors.toList());

        result.put("ownRoleIds", stringList);
        result.put("allRole", sysRoles);

        return R.ok(result);
    }

    @Override
    public R<ResponseCode> updateUserRoles(Map<String, Object> req) {
        long userId = Long.parseLong((String) req.get("userId"));
        List<String> roleIds = (List<String>) req.get("roleIds");
        SysUserRole sysUserRole = new SysUserRole();
        int result = 0;
        int all = sysUserRoleMapper.deleteByUD(userId);
        for (String roleId : roleIds) {
            sysUserRole.setId(idWorker.nextId());
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(Long.parseLong(roleId));
            sysUserRole.setCreateTime(DateTime.now().toDate());
            result = result + sysUserRoleMapper.insert(sysUserRole);
        }
        if (result > 0) {
            return R.ok(ResponseCode.SUCCESS);
        }
        return R.ok(ResponseCode.ERROR);
    }

    @Override
    public R<ResponseCode> deleteUser(List<Long> userList) {
        int result = 0;
        if (userList == null) {
            return null;
        }
        for (Long aLong : userList) {
            result = result + sysUserRoleMapper.deleteByUD(aLong) + sysUserMapper.deleteByPrimaryKey(aLong);
        }
        if (result > 0) {
            return R.ok(ResponseCode.SUCCESS);
        }
        return R.error(ResponseCode.ERROR);
    }

    @Override
    public R<SysUser> getUserInfo(String userId) {
        if (userId == null) {
            System.out.println("=================================================================================================");
            return null;
        }
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(Long.parseLong(userId));
        return R.ok(sysUser);
    }

    @Override
    public R<ResponseCode> updateUserInfo(UserInfoVo userInfoVo) {
        int result = sysUserMapper.updateUserInfo(userInfoVo);
        if (result == 1) {
            return R.ok(ResponseCode.SUCCESS);
        }
        return R.error(ResponseCode.ERROR);
    }

    @Override
    public R<PageResult> getRolePages(Map<String, Integer> pageInfo) {
        PageHelper.startPage(pageInfo.get("pageNum"), pageInfo.get("pageSize"));
        List<SysRole> result = sysRoleMapper.getAllRole();
        PageInfo<SysRole> rolePageInfo = new PageInfo<>(result);
        PageResult<SysRole> rolePageResult = new PageResult<>(rolePageInfo);
        return R.ok(rolePageResult);
    }

    @Override
    public R<List<children>> getPermissionsTree() {

        List<children> majorPMT = sysPermissionMapper.getMajorPMT("");

        ArrayList<children> organization = sysPermissionMapper.getMajorPMT("1");
        ArrayList<children> organUser = sysPermissionMapper.getMajorPMT("%user%");
        ArrayList<children> organRole = sysPermissionMapper.getMajorPMT("%role%");
        ArrayList<children> organPermission = sysPermissionMapper.getMajorPMT("%permission%");
        organization.forEach(e -> {
            if (e.getTitle().equals("用户管理")) {
                e.setChildren(organUser);
            } else if (e.getTitle().equals("角色管理")) {
                e.setChildren(organRole);
            } else if (e.getTitle().equals("菜单权限管理")) {
                e.setChildren(organPermission);
            }
        });

        ArrayList<children> log = sysPermissionMapper.getMajorPMT("%log%");

        majorPMT.forEach(e -> {
            if (e.getTitle().equals("组织管理")) {
                e.setChildren(organization);
            } else if (e.getTitle().equals("日志管理")) {
                e.setChildren(log);
            }
        });
        System.out.println("jj");
        return R.ok(majorPMT);
    }

    @Override
    public R<ResponseCode> addRoleAndPer(Map<String, Object> addRole) throws JsonProcessingException {
        SysRole role = new SysRole();
        long id = idWorker.nextId();
        role.setId(id);
        role.setName(addRole.get("name").toString());
        role.setDescription(addRole.get("description").toString());
        role.setCreateTime(DateTime.now().toDate());
        role.setUpdateTime(DateTime.now().toDate());
        int insertRole = sysRoleMapper.insert(role);

        //使用jackson的json转换器
        ObjectMapper objectMapper = new ObjectMapper();
        // 将 Object 序列化为 JSON 字符串
        String json = objectMapper.writeValueAsString(addRole.get("permissionsIds"));
        // 将 JSON 字符串反序列化为 List<Long> 类型
        List<Long> perIds = objectMapper.readValue(json, new TypeReference<List<Long>>() {});
        //String permissionIds = addRole.get("permissionIds").toString();
        //List<Long> perIds = (List<Long>) addRole.get("permissionIds"); 强转行不通
        for (Long perId : perIds) {
            SysRolePermission sysRolePermission = new SysRolePermission();
            sysRolePermission.setId(idWorker.nextId());
            sysRolePermission.setRoleId(id);
            sysRolePermission.setPermissionId(perId);
            sysRolePermission.setCreateTime(DateTime.now().toDate());
            insertRole = insertRole + sysRolePermissionMapper.insert(sysRolePermission);
        }
        if (insertRole >= 1) {
            return R.ok(ResponseCode.SUCCESS);
        }
        return R.error(ResponseCode.ERROR);
    }

    @Override
    public R<List<String>> getRolePers(String roleId) {

        List<String> result=sysRolePermissionMapper.getRolePers(roleId).stream().map(String::valueOf).collect(Collectors.toList());


        return R.ok(result);
    }

    @Override
    public R<ResponseCode> updateRoleAndPer(Map<String, Object> updateRole) throws JsonProcessingException {

        SysRole role = new SysRole();
        long id =Long.parseLong(updateRole.get("id").toString());
        role.setId(id);
        role.setName(updateRole.get("name").toString());
        role.setDescription(updateRole.get("description").toString());
        role.setCreateTime(DateTime.now().toDate());
        role.setUpdateTime(DateTime.now().toDate());
        int insertRole = sysRoleMapper.updateByPrimaryKey(role);

        sysRolePermissionMapper.deleteByRoleId(id);

        //使用jackson的json转换器
        ObjectMapper objectMapper = new ObjectMapper();
        // 将 Object 序列化为 JSON 字符串
        String json = objectMapper.writeValueAsString(updateRole.get("permissionsIds"));
        // 将 JSON 字符串反序列化为 List<Long> 类型
        List<Long> perIds = objectMapper.readValue(json, new TypeReference<List<Long>>() {});
        //String permissionIds = addRole.get("permissionIds").toString();
        //List<Long> perIds = (List<Long>) addRole.get("permissionIds"); 强转行不通
        for (Long perId : perIds) {
            SysRolePermission sysRolePermission = new SysRolePermission();
            sysRolePermission.setId(idWorker.nextId());
            sysRolePermission.setRoleId(id);
            sysRolePermission.setPermissionId(perId);
            sysRolePermission.setCreateTime(DateTime.now().toDate());
            insertRole = insertRole + sysRolePermissionMapper.insert(sysRolePermission);
        }
        if (insertRole >= 1) {
            return R.ok(ResponseCode.SUCCESS);
        }
        return R.error(ResponseCode.ERROR);
    }

    @Override
    public R<ResponseCode> deleteRoleAndPer(String roleId) {

        int result = sysRolePermissionMapper.deleteByRoleId(Long.parseLong(roleId));
        result=result+sysRoleMapper.deleteByPrimaryKey(Long.parseLong(roleId))+sysUserRoleMapper.deleteByRD(Long.parseLong(roleId));

        if(result>=1){
            return R.ok(ResponseCode.SUCCESS);
        }
        return R.error(ResponseCode.ERROR);
    }

    @Override
    public R<ResponseCode> updateRoleStatus(Long roleId, Long status) {


        int result=sysRoleMapper.updateStatusById(roleId,status);
        if(result==1){
            return R.ok(ResponseCode.SUCCESS);
        }

        return R.error(ResponseCode.ERROR);
    }
}
